home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectDraw / GammaControl / gammacontrol.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  17.9 KB  |  572 lines

  1. //-----------------------------------------------------------------------------
  2. // File: GammaControl.cpp
  3. //
  4. // Desc: This sample demonstrates how to use DirectDraw full-screen mode
  5. //       using the exclusive DirectDraw cooperative level.
  6. //
  7. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <windows.h>
  11. #include <ddraw.h>
  12. #include <mmsystem.h>
  13. #include "resource.h"
  14. #include "ddutil.h"
  15.  
  16.  
  17.  
  18.  
  19. //-----------------------------------------------------------------------------
  20. // Defines, constants, and global variables
  21. //-----------------------------------------------------------------------------
  22. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  23. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  24.  
  25. #define SCREEN_WIDTH        640
  26. #define SCREEN_HEIGHT       480
  27. #define SCREEN_BPP          32
  28.  
  29. #define NUM_COLOR_BARS      63
  30.  
  31. #define HELPTEXT  TEXT("Adjust the gamma level by clicking either mouse button.  Press Escape to quit.")
  32. #define GAMMATEXT TEXT("Displaying with linear gamma ramp between 0 and %0.5d")
  33.  
  34. CDisplay*                g_pDisplay          = NULL;
  35. CSurface*                g_pLogoSurface      = NULL;  
  36. CSurface*                g_pHelpTextSurface  = NULL;  
  37. CSurface*                g_pGammaTextSurface = NULL;  
  38. LPDIRECTDRAWGAMMACONTROL g_pGammaControl = NULL;
  39. BOOL                     g_bActive       = FALSE; 
  40. LONG                     g_lGammaRamp    = 256;
  41.  
  42.  
  43.  
  44.  
  45. //-----------------------------------------------------------------------------
  46. // Function-prototypes
  47. //-----------------------------------------------------------------------------
  48. LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
  49. HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel );
  50. HRESULT InitDirectDraw( HWND hWnd );
  51. VOID    FreeDirectDraw();
  52. BOOL    HasGammaSupport();
  53. HRESULT UpdateGammaRamp();
  54. HRESULT ProcessNextFrame();
  55. HRESULT DisplayFrame();
  56. HRESULT RestoreSurfaces();
  57. HRESULT DrawGammaText();
  58.  
  59.  
  60.  
  61.  
  62. //-----------------------------------------------------------------------------
  63. // Name: WinMain()
  64. // Desc: Entry point to the program. Initializes everything and calls
  65. //       UpdateFrame() when idle from the message pump.
  66. //-----------------------------------------------------------------------------
  67. int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow )
  68. {
  69.     MSG         msg;
  70.     HWND     hWnd;
  71.     HACCEL   hAccel;
  72.     HRESULT  hr;
  73.  
  74.     if( FAILED( WinInit( hInst, nCmdShow, &hWnd, &hAccel ) ) )
  75.         return FALSE;
  76.  
  77.     if( FAILED( InitDirectDraw( hWnd ) ) )
  78.     {
  79.         SAFE_DELETE( g_pDisplay );
  80.  
  81.         MessageBox( hWnd, TEXT("DirectDraw init failed. ")
  82.                     TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  83.                     MB_ICONERROR | MB_OK );
  84.         return FALSE;
  85.     }
  86.  
  87.     if( HasGammaSupport() == FALSE ) 
  88.     {
  89.         SAFE_DELETE( g_pDisplay );
  90.  
  91.         MessageBox( hWnd, TEXT("The primary surface does not support gamma control.  ")
  92.                     TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  93.                     MB_ICONERROR | MB_OK );
  94.         return FALSE;
  95.     }
  96.  
  97.     if( FAILED( hr = g_pDisplay->GetFrontBuffer()->QueryInterface( IID_IDirectDrawGammaControl, 
  98.                                                     (LPVOID*) &g_pGammaControl ) ) )
  99.     {
  100.         SAFE_DELETE( g_pDisplay );
  101.  
  102.         MessageBox( hWnd, TEXT("The primary surface does not support IDirectDrawGammaControl.  ")
  103.                     TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  104.                     MB_ICONERROR | MB_OK );
  105.         return FALSE;
  106.     }
  107.  
  108.     while( TRUE )
  109.     {
  110.         // Look for messages, if none are found then 
  111.         // update the state and display it
  112.         if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  113.         {
  114.             if( 0 == GetMessage(&msg, NULL, 0, 0 ) )
  115.             {
  116.                 // WM_QUIT was posted, so exit
  117.                 return (int)msg.wParam;
  118.             }
  119.  
  120.             // Translate and dispatch the message
  121.             if( 0 == TranslateAccelerator( hWnd, hAccel, &msg ) )
  122.             {
  123.                 TranslateMessage( &msg ); 
  124.                 DispatchMessage( &msg );
  125.             }
  126.         }
  127.         else
  128.         {
  129.             if( g_bActive )
  130.             {
  131.                 // Move the sprites, blt them to the back buffer, then 
  132.                 // flip or blt the back buffer to the primary buffer
  133.                 if( FAILED( ProcessNextFrame() ) )
  134.                 {
  135.                     SAFE_DELETE( g_pDisplay );
  136.  
  137.                     MessageBox( hWnd, TEXT("Displaying the next frame failed. ")
  138.                                 TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  139.                                 MB_ICONERROR | MB_OK );
  140.                     return FALSE;
  141.                 }
  142.             }
  143.             else
  144.             {
  145.                 // Make sure we go to sleep if we have nothing else to do
  146.                 WaitMessage();
  147.             }
  148.         }
  149.     }
  150. }
  151.  
  152.  
  153.  
  154.  
  155. //-----------------------------------------------------------------------------
  156. // Name: WinInit()
  157. // Desc: Init the window
  158. //-----------------------------------------------------------------------------
  159. HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel )
  160. {
  161.     WNDCLASS wc;
  162.     HWND     hWnd;
  163.     HACCEL   hAccel;
  164.  
  165.     // Register the Window Class
  166.     wc.lpszClassName = TEXT("GammaControl");
  167.     wc.lpfnWndProc   = MainWndProc;
  168.     wc.style         = CS_VREDRAW | CS_HREDRAW;
  169.     wc.hInstance     = hInst;
  170.     wc.hIcon         = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN) );
  171.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  172.     wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  173.     wc.lpszMenuName  = NULL;
  174.     wc.cbClsExtra    = 0;
  175.     wc.cbWndExtra    = 0;
  176.  
  177.     if( RegisterClass( &wc ) == 0 )
  178.         return E_FAIL;
  179.  
  180.     // Load keyboard accelerators
  181.     hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
  182.  
  183.     // Create and show the main window
  184.     hWnd = CreateWindowEx( 0, TEXT("GammaControl"), TEXT("DirectDraw GammaControl Sample"),
  185.                            WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
  186.                              CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL );
  187.     if( hWnd == NULL )
  188.         return E_FAIL;
  189.  
  190.     ShowWindow( hWnd, nCmdShow );
  191.     UpdateWindow( hWnd );
  192.  
  193.     *phWnd   = hWnd;
  194.     *phAccel = hAccel;
  195.  
  196.     return S_OK;
  197. }
  198.  
  199.  
  200.  
  201.  
  202. //-----------------------------------------------------------------------------
  203. // Name: InitDirectDraw()
  204. // Desc: Create the DirectDraw object, and init the surfaces
  205. //-----------------------------------------------------------------------------
  206. HRESULT InitDirectDraw( HWND hWnd )
  207. {
  208.     HRESULT             hr;
  209.  
  210.     g_pDisplay = new CDisplay();
  211.     if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH, 
  212.                                                           SCREEN_HEIGHT, SCREEN_BPP ) ) )
  213.     {
  214.         MessageBox( hWnd, TEXT("This display card does not support 640x480x8. "),
  215.                     TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
  216.         return hr;
  217.     }
  218.  
  219.     // Create a surface, and draw text to it.  
  220.     if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pHelpTextSurface, NULL, HELPTEXT, 
  221.                                                         RGB(0,0,0), RGB(255, 255, 0) ) ) )
  222.         return hr;
  223.  
  224.     TCHAR strGammaText[256];
  225.     wsprintf( strGammaText, GAMMATEXT, g_lGammaRamp * 256 );
  226.  
  227.     if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pGammaTextSurface, NULL, strGammaText, 
  228.                                                         RGB(0,0,0), RGB(255, 255, 0) ) ) )
  229.         return hr;
  230.  
  231.     return S_OK;
  232. }
  233.  
  234.  
  235.  
  236.  
  237. //-----------------------------------------------------------------------------
  238. // Name: FreeDirectDraw()
  239. // Desc: Release all the DirectDraw objects
  240. //-----------------------------------------------------------------------------
  241. VOID FreeDirectDraw()
  242. {
  243.     SAFE_DELETE( g_pHelpTextSurface );
  244.     SAFE_DELETE( g_pGammaTextSurface );
  245.     SAFE_DELETE( g_pDisplay );
  246. }
  247.  
  248.  
  249.  
  250.  
  251.  
  252. //-----------------------------------------------------------------------------
  253. // Name: MainWndProc()
  254. // Desc: The main window procedure
  255. //-----------------------------------------------------------------------------
  256. LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  257. {
  258.     switch (msg)
  259.     {
  260.         case WM_LBUTTONDOWN:
  261.             g_lGammaRamp -= 8;
  262.             if( g_lGammaRamp < 0 )
  263.                 g_lGammaRamp = 0;
  264.  
  265.             if( FAILED( UpdateGammaRamp() ) )
  266.             {
  267.                 SAFE_DELETE( g_pDisplay );
  268.  
  269.                 MessageBox( hWnd, TEXT("Failed setting the new gamma level.  ")
  270.                             TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  271.                             MB_ICONERROR | MB_OK );
  272.  
  273.                 PostQuitMessage( 0 );
  274.             }
  275.             break;
  276.  
  277.         case WM_RBUTTONDOWN:
  278.             g_lGammaRamp += 8;
  279.             if( g_lGammaRamp > 256 )
  280.                 g_lGammaRamp = 256;
  281.  
  282.             if( FAILED( UpdateGammaRamp() ) )
  283.             {
  284.                 SAFE_DELETE( g_pDisplay );
  285.  
  286.                 MessageBox( hWnd, TEXT("Failed setting the new gamma level.  ")
  287.                             TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  288.                             MB_ICONERROR | MB_OK );
  289.  
  290.                 PostQuitMessage( 0 );
  291.             }
  292.             break;
  293.  
  294.         case WM_COMMAND:
  295.             switch( LOWORD(wParam) )
  296.             {
  297.                 case IDM_EXIT:
  298.                     // Received key/menu command to exit app
  299.                     PostMessage( hWnd, WM_CLOSE, 0, 0 );
  300.                     return 0L;
  301.             }
  302.             break; // Continue with default processing
  303.  
  304.         case WM_SETCURSOR:
  305.             // Hide the cursor in fullscreen 
  306.             SetCursor( NULL );
  307.             return TRUE;
  308.  
  309.         case WM_SIZE:
  310.             // Check to see if we are losing our window...
  311.             if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
  312.                 g_bActive = FALSE;
  313.             else
  314.                 g_bActive = TRUE;
  315.             break;
  316.             
  317.         case WM_SYSCOMMAND:
  318.             // Prevent moving/sizing and power loss in fullscreen mode
  319.             switch( wParam )
  320.             {
  321.                 case SC_MOVE:
  322.                 case SC_SIZE:
  323.                 case SC_MAXIMIZE:
  324.                 case SC_MONITORPOWER:
  325.                     return TRUE;
  326.             }
  327.             break;
  328.             
  329.         case WM_DESTROY:
  330.             // Cleanup and close the app
  331.             FreeDirectDraw();
  332.             PostQuitMessage( 0 );
  333.             return 0L;
  334.     }
  335.  
  336.     return DefWindowProc(hWnd, msg, wParam, lParam);
  337. }
  338.  
  339.  
  340.  
  341.  
  342. //-----------------------------------------------------------------------------
  343. // Name: HasGammaSupport()
  344. // Desc: Returns TRUE if the device supports gamma control, FALSE otherwise
  345. //-----------------------------------------------------------------------------
  346. BOOL HasGammaSupport()
  347. {
  348.     // Get driver capabilities to determine gamma support.
  349.     DDCAPS  ddcaps;    
  350.     ZeroMemory( &ddcaps, sizeof(ddcaps) );
  351.     ddcaps.dwSize = sizeof(ddcaps);
  352.  
  353.     g_pDisplay->GetDirectDraw()->GetCaps( &ddcaps, NULL );
  354.     
  355.     // Does the driver support gamma? 
  356.     // The DirectDraw emulation layer does not support overlays
  357.     // so gamma related APIs will fail without hardware support.  
  358.     if( ddcaps.dwCaps2 & DDCAPS2_PRIMARYGAMMA )
  359.         return TRUE;
  360.     else
  361.         return FALSE;    
  362. }
  363.  
  364.  
  365.  
  366.  
  367. //-----------------------------------------------------------------------------
  368. // Name: UpdateGammaRamp()
  369. // Desc: 
  370. //-----------------------------------------------------------------------------
  371. HRESULT UpdateGammaRamp()
  372. {
  373.     HRESULT     hr;
  374.     DDGAMMARAMP ddgr;
  375.     WORD dwGamma;
  376.  
  377.     ZeroMemory( &ddgr, sizeof(ddgr) );
  378.  
  379.     if( FAILED( hr = g_pGammaControl->GetGammaRamp( 0, &ddgr ) ) )
  380.         return hr;
  381.  
  382.     dwGamma = 0;
  383.  
  384.     for( int iColor = 0; iColor < 256; iColor++ )
  385.     {
  386.         ddgr.red[iColor]   = dwGamma;
  387.         ddgr.green[iColor] = dwGamma;
  388.         ddgr.blue[iColor]  = dwGamma;
  389.  
  390.         dwGamma += (WORD) g_lGammaRamp;
  391.     }
  392.  
  393.     if( FAILED( hr = g_pGammaControl->SetGammaRamp( 0, &ddgr ) ) )
  394.         return hr;
  395.  
  396.     if( FAILED( hr = DrawGammaText() ) )
  397.         return hr;
  398.  
  399.     return S_OK;
  400. }
  401.  
  402.  
  403.  
  404.  
  405. //-----------------------------------------------------------------------------
  406. // Name: ProcessNextFrame()
  407. // Desc: Move the sprites, blt them to the back buffer, then 
  408. //       flips the back buffer to the primary buffer
  409. //-----------------------------------------------------------------------------
  410. HRESULT ProcessNextFrame()
  411. {
  412.     HRESULT hr;
  413.  
  414.     // Display the sprites on the screen
  415.     if( FAILED( hr = DisplayFrame() ) )
  416.     {
  417.         if( hr != DDERR_SURFACELOST )
  418.             return hr;
  419.  
  420.         // The surfaces were lost so restore them 
  421.         RestoreSurfaces();
  422.     }
  423.  
  424.     return S_OK;
  425. }
  426.  
  427.  
  428.  
  429.  
  430. //-----------------------------------------------------------------------------
  431. // Name: DisplayFrame()
  432. // Desc: Blts a the color bars to the back buffer, then flips the 
  433. //       back buffer onto the primary buffer.
  434. //-----------------------------------------------------------------------------
  435. HRESULT DisplayFrame()
  436. {
  437.     DDSURFACEDESC2 ddsd;
  438.     HRESULT hr;
  439.     DDBLTFX ddbltfx;
  440.     RECT    rctDest;
  441.     DWORD   dwRShift;
  442.     DWORD   dwGShift;
  443.     DWORD   dwBShift;
  444.     DWORD   dwRColorLevels;
  445.     DWORD   dwGColorLevels;
  446.     DWORD   dwBColorLevels;
  447.     DWORD   dwBits;
  448.     DWORD   dwColor;
  449.     LPDIRECTDRAWSURFACE7 pFrontBuffer;
  450.     LPDIRECTDRAWSURFACE7 pBackBuffer;
  451.  
  452.     pFrontBuffer = g_pDisplay->GetFrontBuffer();
  453.     pBackBuffer = g_pDisplay->GetBackBuffer();
  454.  
  455.     ZeroMemory( &ddsd,sizeof(ddsd) );
  456.     ddsd.dwSize = sizeof(ddsd);
  457.     if( FAILED( hr = pFrontBuffer->GetSurfaceDesc( &ddsd ) ) )
  458.         return hr;
  459.  
  460.     // Fill the back buffer with black, ignoring errors until the flip
  461.     g_pDisplay->Clear(0);
  462.  
  463.     CSurface::GetBitMaskInfo( ddsd.ddpfPixelFormat.dwRBitMask, &dwRShift, &dwBits );
  464.     CSurface::GetBitMaskInfo( ddsd.ddpfPixelFormat.dwGBitMask, &dwGShift, &dwBits );
  465.     CSurface::GetBitMaskInfo( ddsd.ddpfPixelFormat.dwBBitMask, &dwBShift, &dwBits );
  466.  
  467.     dwRColorLevels = ddsd.ddpfPixelFormat.dwRBitMask >> dwRShift;
  468.     dwGColorLevels = ddsd.ddpfPixelFormat.dwGBitMask >> dwGShift;
  469.     dwBColorLevels = ddsd.ddpfPixelFormat.dwBBitMask >> dwBShift;
  470.  
  471.     ZeroMemory( &ddbltfx, sizeof(ddbltfx) );
  472.     ddbltfx.dwSize      = sizeof(ddbltfx);
  473.  
  474.     for( DWORD i = 0; i <= NUM_COLOR_BARS; i++ )
  475.     {
  476.         rctDest.left   = SCREEN_WIDTH / (NUM_COLOR_BARS + 1) * (i + 0);
  477.         rctDest.right  = SCREEN_WIDTH / (NUM_COLOR_BARS + 1) * (i + 1);
  478.  
  479.         // Figure out the color for the red color bar
  480.         dwColor = (DWORD) ( dwRColorLevels * i / (float) NUM_COLOR_BARS );
  481.         ddbltfx.dwFillColor = dwColor << dwRShift;
  482.  
  483.         rctDest.top    = SCREEN_HEIGHT / 3 * 0;
  484.         rctDest.bottom = SCREEN_HEIGHT / 3 * 1;
  485.         pBackBuffer->Blt( &rctDest, NULL, NULL, 
  486.                          DDBLT_COLORFILL | DDBLT_WAIT, 
  487.                          &ddbltfx );
  488.  
  489.         // Figure out the color for the green color bar
  490.         dwColor = (DWORD) ( dwGColorLevels * i / (float) NUM_COLOR_BARS );
  491.         ddbltfx.dwFillColor = dwColor << dwGShift;
  492.  
  493.         rctDest.top    = SCREEN_HEIGHT / 3 * 1;
  494.         rctDest.bottom = SCREEN_HEIGHT / 3 * 2;
  495.         pBackBuffer->Blt( &rctDest, NULL, NULL, 
  496.                          DDBLT_COLORFILL | DDBLT_WAIT, 
  497.                          &ddbltfx );
  498.  
  499.         // Figure out the color for the blue color bar
  500.         dwColor = (DWORD) ( dwBColorLevels * i / (float) NUM_COLOR_BARS );
  501.         ddbltfx.dwFillColor = dwColor << dwBShift;
  502.  
  503.         rctDest.top    = SCREEN_HEIGHT / 3 * 2;
  504.         rctDest.bottom = SCREEN_HEIGHT / 3 * 3;
  505.         pBackBuffer->Blt( &rctDest, NULL, NULL, 
  506.                          DDBLT_COLORFILL | DDBLT_WAIT, 
  507.                          &ddbltfx );
  508.  
  509.     }
  510.  
  511.     // Blt the help text on the backbuffer, ignoring errors until the flip
  512.     g_pDisplay->Blt( 10, 10, g_pHelpTextSurface, NULL );
  513.  
  514.     g_pDisplay->Blt( 10, 30, g_pGammaTextSurface, NULL );
  515.  
  516.     // We are in fullscreen mode, so perform a flip and return 
  517.     // any errors like DDERR_SURFACELOST
  518.     if( FAILED( hr = g_pDisplay->Present() ) )
  519.         return hr;
  520.  
  521.     return S_OK;
  522. }
  523.  
  524.  
  525.  
  526.  
  527. //-----------------------------------------------------------------------------
  528. // Name: RestoreSurfaces()
  529. // Desc: Restore all the surfaces, and redraw the sprite surfaces.
  530. //-----------------------------------------------------------------------------
  531. HRESULT RestoreSurfaces()
  532. {
  533.     HRESULT hr;
  534.  
  535.     if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) )
  536.         return hr;
  537.  
  538.     // No need to re-create the surface, just re-draw it.
  539.     if( FAILED( hr = g_pHelpTextSurface->DrawText( NULL, HELPTEXT, 
  540.                                                    0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  541.         return hr;
  542.  
  543.     DrawGammaText();
  544.  
  545.     return S_OK;
  546. }
  547.  
  548.  
  549.  
  550.  
  551. //-----------------------------------------------------------------------------
  552. // Name: DrawGammaText()
  553. // Desc: 
  554. //-----------------------------------------------------------------------------
  555. HRESULT DrawGammaText()
  556. {
  557.     HRESULT hr;
  558.     TCHAR   strGammaText[256];
  559.  
  560.     wsprintf( strGammaText, GAMMATEXT, g_lGammaRamp * 256 );
  561.  
  562.     if( FAILED( hr = g_pGammaTextSurface->DrawText( NULL, strGammaText, 
  563.                                                     0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  564.         return hr;
  565.  
  566.     return S_OK;
  567. }
  568.  
  569.  
  570.  
  571.  
  572.